package com.christina.engine.parameter.builder;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * 参数建造者抽象基类
 * 使用建造者模式构建复杂的参数对象，提供验证和转换功能
 * 
 * @param <T> 要构建的参数对象类型
 * @author Christina
 */
public abstract class ParameterBuilder<T> {
    
    protected final Map<String, Object> parameters = new HashMap<>();
    protected final Map<String, ValidationRule> validationRules = new HashMap<>();
    protected final Map<String, Function<Object, Object>> converters = new HashMap<>();
    protected final Map<String, Object> defaultValues = new HashMap<>();
    
    /**
     * 添加参数
     * 
     * @param key 参数键
     * @param value 参数值
     * @return 当前建造者实例
     */
    public ParameterBuilder<T> addParameter(String key, Object value) {
        if (key != null && value != null) {
            parameters.put(key, value);
        }
        return this;
    }
    
    /**
     * 批量添加参数
     * 
     * @param params 参数映射
     * @return 当前建造者实例
     */
    public ParameterBuilder<T> addParameters(Map<String, Object> params) {
        if (params != null) {
            parameters.putAll(params);
        }
        return this;
    }
    
    /**
     * 添加验证规则
     * 
     * @param key 参数键
     * @param validator 验证器
     * @param errorMessage 错误信息
     * @return 当前建造者实例
     */
    public ParameterBuilder<T> addValidation(String key, Predicate<Object> validator, String errorMessage) {
        validationRules.put(key, new ValidationRule(validator, errorMessage));
        return this;
    }
    
    /**
     * 添加必需参数验证
     * 
     * @param key 参数键
     * @return 当前建造者实例
     */
    public ParameterBuilder<T> required(String key) {
        return addValidation(key, 
                value -> value != null && !value.toString().trim().isEmpty(),
                "参数 " + key + " 是必需的");
    }
    
    /**
     * 添加类型转换器
     * 
     * @param key 参数键
     * @param converter 转换器
     * @return 当前建造者实例
     */
    public ParameterBuilder<T> addConverter(String key, Function<Object, Object> converter) {
        converters.put(key, converter);
        return this;
    }
    
    /**
     * 设置默认值
     * 
     * @param key 参数键
     * @param defaultValue 默认值
     * @return 当前建造者实例
     */
    public ParameterBuilder<T> setDefault(String key, Object defaultValue) {
        defaultValues.put(key, defaultValue);
        return this;
    }
    
    /**
     * 验证所有参数
     * 
     * @throws ParameterValidationException 如果验证失败
     */
    public ParameterBuilder<T> validate() throws ParameterValidationException {
        // 应用默认值
        applyDefaults();
        
        // 应用类型转换
        applyConverters();
        
        // 执行验证
        for (Map.Entry<String, ValidationRule> entry : validationRules.entrySet()) {
            String key = entry.getKey();
            ValidationRule rule = entry.getValue();
            Object value = parameters.get(key);
            
            if (!rule.validator.test(value)) {
                throw new ParameterValidationException(rule.errorMessage);
            }
        }
        
        // 执行自定义验证
        performCustomValidation();
        
        return this;
    }
    
    /**
     * 构建参数对象
     * 
     * @return 构建的参数对象
     * @throws ParameterValidationException 如果验证失败
     */
    public T build() throws ParameterValidationException {
        validate();
        return doBuild();
    }
    
    /**
     * 获取参数值
     * 
     * @param key 参数键
     * @param type 参数类型
     * @return 参数值
     */
    @SuppressWarnings("unchecked")
    protected <V> V getParameter(String key, Class<V> type) throws ParameterValidationException {
        Object value = parameters.get(key);
        if (value == null) {
            return null;
        }
        
        if (type.isInstance(value)) {
            return (V) value;
        }
        
        // 尝试基本类型转换
        return convertValue(value, type);
    }
    
    /**
     * 获取参数值，如果不存在则返回默认值
     * 
     * @param key 参数键
     * @param type 参数类型
     * @param defaultValue 默认值
     * @return 参数值或默认值
     */
    protected <V> V getParameter(String key, Class<V> type, V defaultValue) throws ParameterValidationException {
        V value = getParameter(key, type);
        return value != null ? value : defaultValue;
    }
    
    /**
     * 检查参数是否存在
     * 
     * @param key 参数键
     * @return 是否存在
     */
    protected boolean hasParameter(String key) {
        return parameters.containsKey(key) && parameters.get(key) != null;
    }
    
    /**
     * 应用默认值
     */
    private void applyDefaults() {
        for (Map.Entry<String, Object> entry : defaultValues.entrySet()) {
            String key = entry.getKey();
            if (!parameters.containsKey(key) || parameters.get(key) == null) {
                parameters.put(key, entry.getValue());
            }
        }
    }
    
    /**
     * 应用类型转换
     */
    private void applyConverters() {
        for (Map.Entry<String, Function<Object, Object>> entry : converters.entrySet()) {
            String key = entry.getKey();
            if (parameters.containsKey(key)) {
                Object value = parameters.get(key);
                if (value != null) {
                    parameters.put(key, entry.getValue().apply(value));
                }
            }
        }
    }
    
    /**
     * 值类型转换
     * 
     * @param value 原始值
     * @param type 目标类型
     * @return 转换后的值
     */
    @SuppressWarnings("unchecked")
    private <V> V convertValue(Object value, Class<V> type) throws ParameterValidationException {
        if (value == null) {
            return null;
        }
        
        String stringValue = value.toString();
        
        try {
            if (type == String.class) {
                return (V) stringValue;
            } else if (type == Integer.class || type == int.class) {
                return (V) Integer.valueOf(stringValue);
            } else if (type == Long.class || type == long.class) {
                return (V) Long.valueOf(stringValue);
            } else if (type == Double.class || type == double.class) {
                return (V) Double.valueOf(stringValue);
            } else if (type == Boolean.class || type == boolean.class) {
                return (V) Boolean.valueOf(stringValue);
            }
        } catch (NumberFormatException e) {
            throw new ParameterValidationException("无法将值 '" + stringValue + "' 转换为类型 " + type.getSimpleName());
        }
        
        throw new ParameterValidationException("不支持的类型转换: " + type.getSimpleName());
    }
    
    /**
     * 执行自定义验证逻辑
     * 子类可以重写此方法来实现特定的验证逻辑
     * 
     * @throws ParameterValidationException 如果验证失败
     */
    protected void performCustomValidation() throws ParameterValidationException {
        // 默认实现为空，子类可以重写
    }
    
    /**
     * 执行实际的构建逻辑
     * 子类必须实现此方法
     * 
     * @return 构建的参数对象
     */
    protected abstract T doBuild() throws ParameterValidationException;
    
    /**
     * 验证规则内部类
     */
    private static class ValidationRule {
        final Predicate<Object> validator;
        final String errorMessage;
        
        ValidationRule(Predicate<Object> validator, String errorMessage) {
            this.validator = validator;
            this.errorMessage = errorMessage;
        }
    }
    
    /**
     * 参数验证异常
     */
    public static class ParameterValidationException extends Exception {
        public ParameterValidationException(String message) {
            super(message);
        }
        
        public ParameterValidationException(String message, Throwable cause) {
            super(message, cause);
        }
    }
}